package com.zsn.demo.test.threadPool;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @program: threadDemo
 * @ClassName BlockingQueue
 * @description:
 * @author: zsn
 * @create: 2025-03-12 16:39
 * @Version 1.0
 **/
class BlockingQueue<T> {
    //阻塞队列，存放任务
    private Deque<T> queue = new ArrayDeque<>();
    // 队列的最大容量
    private int capacity;
    // 锁
    private ReentrantLock lock = new ReentrantLock();
    // 生产者条件变量
    private Condition fullWaitSet = lock.newCondition();
    // 消费者生产变量
    private Condition emptyWaitSet = lock.newCondition();
    // 构造方法
    public BlockingQueue(int capacity) {
        this.capacity = capacity;
    }
    // 超时阻塞获取
    public T poll(Long timeOut, TimeUnit timeUnit){
        lock.lock();
        // 将时间转为纳秒
        long nanos = timeUnit.toNanos(timeOut);
        try {
            while (queue.isEmpty()){
                try {
                    if (nanos <= 0){
                        return null;
                    }
                    nanos = emptyWaitSet.awaitNanos(nanos);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            T t = queue.pollFirst();
            fullWaitSet.signal();
            return t;
        } finally {
            lock.unlock();
        }
    }

    // 阻塞获取
    public T take(){
        lock.lock();
        try {
            while (queue.isEmpty()){
                try {
                    emptyWaitSet.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            T t = queue.pollFirst();
            fullWaitSet.signal();
            return t;
        } finally {
            lock.unlock();
        }
    }

    // 超时阻塞添加
    public void offer(T t, long timeout,TimeUnit timeUnit){
        try {
            lock.lock();
            long nanos = timeUnit.toNanos(timeout);
            while (queue.size() == capacity){
                if (nanos <= 0){
                    return;
                }
                try {
                    System.out.println(Thread.currentThread().toString() + "等待加入任务队列:" + t.toString());
                    nanos = fullWaitSet.awaitNanos(nanos);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println(Thread.currentThread().toString() + "加入任务队列:" + t.toString());
            queue.addLast(t);
            emptyWaitSet.signal();
        } finally {
            lock.unlock();
        }
    }

    //阻塞添加
    public void put(T t){
        lock.lock();
        try{
            while (queue.size() == capacity){
                try {
                    System.out.println(Thread.currentThread().toString() + "等待加入任务队列:" + t.toString());
                    fullWaitSet.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().toString() + "加入任务队列:" + t.toString());
            queue.addLast(t);
            emptyWaitSet.signal();
        }finally {
            lock.unlock();
        }
    }

    public int size(){
        lock.lock();
        try{
            return queue.size();
        }finally{
            lock.unlock();
        }
    }

    public void tryPut(RejectPolicy rejectPolicy, T task){
        try {
            lock.lock();
            if (queue.size() == capacity){
                rejectPolicy.reject(this, task);
            } else {
                System.out.println("加入任务队列：" + task);
                queue.addLast(task);
                emptyWaitSet.signal();
            }
        } finally {
            lock.unlock();
        }
    }

}